#include<iostream>
#include<cassert>
#include<cstdlib>
#include<cstring>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<fcntl.h>
#include <sys/wait.h>
#include<cassert>


using namespace std;


int main()
{
    //1、父进程创建管道
    int fds[2];//用于接收管道文件的文件描述符
    int n=pipe(fds);//创建管道，并用fds数组接收读写端的文件描述符
    assert(n==0);//n为0，则管道创建成功

    //2、创建子进程
    int fd=fork();//创建子进程
    assert(fd>=0);//fd<0则创建子进程失败
    if(fd==0)//子进程（从管道读数据
    {
        close(fds[1]);//子进程先关闭写端
        char buffer[1024];//存储从管道中读取到的数据
        while(true)
        {
            //sleep(2);//每隔两秒读一次

            ssize_t s=read(fds[0],buffer,sizeof(buffer)-1);//从管道中读取数据
            buffer[s]=0;//在读取到的数据后追加\0
            if(s>0)//成功读取数据
            {
                cout<<buffer<<" | id: "<<getpid()<<endl;
            }
            else//s==0，写端已关闭，停止通信
            {
                cout<<"写端已关闭，停止通信"<<endl;
                break;
            }

            //break;//只读一次
        }
        close(fds[0]);//子进程关闭读端
        exit(0);//结束子进程
    }
    
    //父进程（向管道写数据

    //3、父进程给子进程发消息
    close(fds[0]);//父进程先关闭读端

    const char* str="我是父进程，我正在给你发消息";//消息内容

    int cnt=1;
    while(true)//给子进程发消息
    {
        char buffer[1024];//存储要发送的消息
        snprintf(buffer,sizeof(buffer),"father->sun:%s[%d][%d]",str,cnt++,getpid());
        write(fds[1],buffer,strlen(buffer));//将buffer中消息发送给子进程
        sleep(2);//每隔2秒写一条消息

        //break;//只写一次
    }
    close(fds[1]);//父进程关闭写端

    //4、父进程回收子进程
    n=waitpid(fd,nullptr,0);//阻塞等待
    assert(n==fd);//等待成功返回子进程id
    return 0;
}
